﻿using Abp.Application.Services.Dto;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Microsoft.EntityFrameworkCore;
using Camc.Quality.Bop.Dto;
using Camc.Quality.Quality;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Linq.Extensions;
using System.Linq.Dynamic.Core;
using Camc.Quality.Authorization.Users;
using Camc.Quality.Authorization.Roles;
using Abp.Authorization.Users;
using Abp.UI;
using Camc.Quality.IOperationHistory;
using Camc.Quality.ProcessRoute;
using Camc.Quality.Common;

namespace Camc.Quality.Bop
{
    public class BopContentAppService : QualityAppServiceBase
    {
        private readonly IRepository<BopDesc, Guid> _bopDescRepository;
        private readonly IRepository<BopNode, Guid> _bopNodeRepository;
        private readonly IRepository<BopContent, Guid> _bopContentEntityRepository;
        private readonly IRepository<TechniqueEntity, Guid> _techniqueEntityRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly RoleManager _roleManager;
        private readonly IRepository<UserRole, long> _userRoleRepository;
        private readonly IRepository<Role> _roleRepository;
        private readonly IOperationHistoryAppService _iOperationHistoryAppService;
        private readonly IRepository<ProcessLine, Guid> _processLineRepository;
        private readonly IRepository<ProcessesEntity, Guid> _processesEntityRepository;
        private readonly IRepository<WorkStepEntity, Guid> _workStepEntityRepository;
        public BopContentAppService(IOperationHistoryAppService iOperationHistoryAppService,
            IRepository<BopNode, Guid> bopNodeRepository,
            IRepository<BopContent, Guid> bopContentEntityRepository,
            IRepository<TechniqueEntity, Guid> techniqueEntityRepository,
            IRepository<User, long> userRepository,
            IRepository<UserRole, long> UserRoleRepository,
            IRepository<Role> RoleRepository,
            RoleManager roleManager,
            IRepository<BopDesc, Guid> bopDescRepository,
            IRepository<ProcessLine, Guid> processLineRepository,
            IRepository<ProcessesEntity, Guid> processesEntityRepository,
            IRepository<WorkStepEntity, Guid> workStepEntityRepository)
        {
            _iOperationHistoryAppService = iOperationHistoryAppService;
            _roleManager = roleManager;
            _bopNodeRepository = bopNodeRepository;
            _bopContentEntityRepository = bopContentEntityRepository;
            _techniqueEntityRepository = techniqueEntityRepository;
            _userRepository = userRepository;
            _userRoleRepository = UserRoleRepository;
            _roleRepository = RoleRepository;
            _bopDescRepository = bopDescRepository;
            _processLineRepository = processLineRepository;
            _processesEntityRepository = processesEntityRepository;
            _workStepEntityRepository = workStepEntityRepository;
        }

        
        /// <summary>
        /// Bop节点新增和修改接口，根据是否传输id判断（只针对2,、3、4）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task CreateOrUpdateBopContent(CreateOrUpdateBopContentInput input)
        {
            if (input.BopContent.Id == Guid.Empty)
            {
                await CreateBopContent(input);
            }
            else
            {
                await UpdateBopContent(input);
            }
        }
        /// <summary>
        /// Bop备注 Insert
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task CreateBopContent(CreateOrUpdateBopContentInput input)
        {
            //var releaseUserId = AbpSession.UserId;
            var bop = new BopContent()
            {
                BopNodeId = input.BopContent.BopNodeId,
                Remark = input.BopContent.Remark,
            };
            if (!string.IsNullOrEmpty(bop.Remark))
                await _bopContentEntityRepository.InsertAsync(bop);
        }
        /// <summary>
        /// Bop备注更新方法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task UpdateBopContent(CreateOrUpdateBopContentInput input)
        {
            var bop = await _bopContentEntityRepository.FirstOrDefaultAsync(c => c.Id == input.BopContent.Id);
            bop.Remark = input.BopContent.Remark;
            //var bopNew = ObjectMapper.Map(input.BopContent, bop);
            await _bopContentEntityRepository.UpdateAsync(bop);
        }
        /// <summary>
        /// 工艺规程文件导入文件选取
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        //public async Task<List<ProcessFileDto>> GetProcessFileList(GetProcessFileListInput input)
        //{
        //    /* and
        //     * var query = _techniqueEntityRepository.GetAll().WhereIf(!input.TechniqueName.IsNullOrWhiteSpace(), x => x.TechniqueName.Contains(input.TechniqueName))
        //                                                   .WhereIf(!input.TechniqueNumber.IsNullOrWhiteSpace(), x => x.TechniqueNumber.Contains(input.TechniqueNumber))
        //                                                   .WhereIf(!input.ModuleCode.IsNullOrWhiteSpace(), x => x.ModuleCode.Contains(input.ModuleCode));*/
        //    /* Filter
        //     * var query = _techniqueEntityRepository.GetAll().WhereIf(!input.Filter.IsNullOrWhiteSpace(),
        //        x => x.TechniqueNumber.Contains(input.Filter) ||
        //        x.TechniqueName.Contains(input.Filter) ||
        //        x.ModuleCode.Contains(input.Filter)
        //        );*/
        //    var query = _techniqueEntityRepository.GetAll().WhereIf(!input.TechniqueName.IsNullOrWhiteSpace(), x => x.TechniqueName.Contains(input.TechniqueName))
        //                                                   .WhereIf(!input.TechniqueNumber.IsNullOrWhiteSpace(), x => x.TechniqueNumber.Contains(input.TechniqueNumber))
        //                                                   .WhereIf(!input.ModuleCode.IsNullOrWhiteSpace(), x => x.ModuleCode.Contains(input.ModuleCode));
        //    var count = await query.CountAsync();
        //    if (count==0)
        //    {
        //        throw new UserFriendlyException("未找到相关文档信息");
        //    }
        //    var list = ObjectMapper.Map<List<ProcessFileDto>>(query);
        //    return list;
        //}
        public async Task<PagedResultDto<ProcessFileDto>> GetProcessFileList(GetProcessFileListInput input)
        {
            var nodeList = _bopNodeRepository.GetAll().Where(t => t.TechniqueEntityId != null).Select(d => d.TechniqueEntityId);
            var query = _techniqueEntityRepository.GetAll().Where(w =>! nodeList.Contains(w.Id) && (w.FileStatus == FileStatus.新增 || w.FileStatus == null))
                .WhereIf(!input.Filter.IsNullOrWhiteSpace() || !input.Filter.IsNullOrWhiteSpace() || !input.Filter.IsNullOrWhiteSpace(),
                x => x.TechniqueNumber.Contains(input.Filter) ||
                x.TechniqueName.Contains(input.Filter) ||
                x.ModuleCode.Contains(input.Filter)
                );
            var count = await query.CountAsync();
            /*if (count == 0)
            {
                throw new UserFriendlyException("未找到相关文档信息");
            }*/
            var bopDescList = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync();
            var list = ObjectMapper.Map<List<ProcessFileDto>>(bopDescList);
            return new PagedResultDto<ProcessFileDto>(count, list);
        }
        /// <summary>
        /// Bop部套描述窗口
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BopContentInfoDto> GetBopContentInfoList(GetBopContentInfoInput input)
        {
            var bop = await _bopNodeRepository.GetAll().Include(c => c.BopContents).FirstOrDefaultAsync(p => p.Id == input.NodeId);
            var bopContentInfo = new BopContentInfoDto();
            if (bop != null)
            {
                var tech = await _techniqueEntityRepository.FirstOrDefaultAsync(c => c.Id == bop.TechniqueEntityId);
                
                if (bop != null)
                {
                    bopContentInfo.NodeDrawingNo = bop.NodeDrawingNo;
                    bopContentInfo.NodeName = bop.NodeName;
                    if (bop.BopContents != null)
                    {
                        bopContentInfo.ContentId = bop.BopContents.Id;
                        bopContentInfo.Remark = bop.BopContents.Remark;
                    }
                }
                if (tech != null)
                {
                    bopContentInfo.ProcessCode = bop.ProcessCode;
                    bopContentInfo.ProcessName = tech.TechniqueName;
                    bopContentInfo.NodeStageSign = tech.StageSign;
                    bopContentInfo.NodeStageSignDesc = ((StageSigns)tech.StageSign).ToString();
                    bopContentInfo.PadName = bop.PadName;
                    bopContentInfo.ExportDate = bop.ExportDate;
                    bopContentInfo.RelationDate = bop.RelationDate;
                    bopContentInfo.TechniqueExplain = tech.TechniqueExplain;
                }
            }
            return bopContentInfo;
        }
        /// <summary>
        /// 工艺规程文件关联
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ResultMessage BopRelationFile(GetBopRelationInput input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                var bop = _bopNodeRepository.FirstOrDefault(c => c.Id == input.NodeId);
                int isLeaf = bop.IsLeaf;
                int nodeLevel = bop.NodeLevel;
                //叶子节点才可以绑定工艺规程
                if (isLeaf == 1)
                {
                    //部套级别
                    if ((nodeLevel == 2) || (nodeLevel == 3))
                    {
                        Guid bopDescId = bop.BopDescId;

                        var techNumCount= _bopNodeRepository.Count(p => p.ProcessCode == input.TechniqueNumber&&p.BopDescId== bop.BopDescId);

                        if (techNumCount > 0)
                        {
                            resultMessage.code = 1;
                            resultMessage.Message = "已绑定该相同工艺规程编号的规程!";
                            return resultMessage;
                            //throw new UserFriendlyException("工艺规程文件已被绑定过,不能重复使用!");
                        }
                        //防错:一本工艺文件只能绑定一次
                        int i = _bopNodeRepository.Count(p => p.TechniqueEntityId == input.TechniqueEntityId);
                        if (i > 0)
                        {
                            resultMessage.code = 1;
                            resultMessage.Message = "工艺规程文件已被绑定过,不能重复使用!";
                            return resultMessage;
                            //throw new UserFriendlyException("工艺规程文件已被绑定过,不能重复使用!");
                        }
                        else
                        {
                            bop.ProcessCode = input.TechniqueNumber;
                            bop.TechniqueEntityId = input.TechniqueEntityId;
                            _bopNodeRepository.Update(bop);
                            //获取任务ID,修改任务表状态为已关联
                            var bopDesc = _bopDescRepository.FirstOrDefault(c => c.Id == bopDescId);
                            bop.RelationDate = DateTime.Now;
                            bopDesc.Status = (Status)2;
                            bopDesc.ProcessStatus = ProcessStatus.已发布;
                            _bopDescRepository.Update(bopDesc);
                            _iOperationHistoryAppService.InsertOperationLog(bop.BopDescId, 0, 3, bop.NodeName + "导入工艺规程");

                            //默认工艺路线
                            //默认线 点 线表_processLineRepository   点表 bopnode 记录坐标 x,y
                            var nodeLine = _processLineRepository.GetAll().Where(d => d.PPtr == bop.Id);
                            var techLine = _processLineRepository.GetAll().Where(d => d.PPtr == input.TechniqueEntityId);
                            //如果已存在则更新数据 不存在就默认生成
                            if (techLine.Count() > 0)
                            {
                                //线表 记录pptr pptr 为当前线父亲节点 bopdesid为 任务id
                                foreach (var item in techLine)
                                {
                                    item.PPtr = bop.Id;
                                    item.BopDescId = bop.BopDescId;
                                    _processLineRepository.Update(item);
                                }
                            }
                            else
                            {
                                if (nodeLine.Count() == 0)
                                {
                                    var processList = _processesEntityRepository.GetAll().Where(d => d.TechniqueEntityId == input.TechniqueEntityId).OrderByDescending(d => d.ProcessesSequence);
                                    double x = 0;
                                    double y = 0;
                                    //默认生成的规则 x 偏右 300 单位 y 向下250单位
                                    if (!string.IsNullOrEmpty(bop.Loc))
                                    {
                                        var locArray = bop.Loc.Split(' ');
                                        if (locArray.Length == 2)
                                        {
                                            x = Convert.ToDouble(locArray[0]) + 300;
                                            y = Convert.ToDouble(locArray[1]) - 250;
                                        }
                                    }
                                    Guid to = bop.Id;
                                    var fpro = processList.Select(d => d.Id);

                                    var proLineCo = (from cc in _processLineRepository.GetAll()
                                                     join mm in fpro on cc.From equals mm
                                                     select cc).Count();
                                    if (proLineCo == 0)
                                    {
                                        //工序 路线
                                        foreach (var item in processList)
                                        {
                                            ProcessLine processLine = new ProcessLine();
                                            processLine.PPtr = bop.Id;
                                            processLine.From = item.Id;
                                            processLine.To = to;
                                            processLine.BopDescId = bopDesc.Id;
                                            to = item.Id;
                                            _processLineRepository.Insert(processLine);
                                            item.Figure = "RoundedRectangle";
                                            item.Color = "black";
                                            item.Size = 0;
                                            item.Fill = "lightgray";
                                            x = x + 300.00;
                                            string loc = x.ToString() + " " + y.ToString();
                                            item.Loc = loc;
                                            _processesEntityRepository.Update(item);

                                            var workStepList = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == item.Id).OrderByDescending(d => d.WorkStepNumber);

                                            double workX = x + 300; ;
                                            double workY = y - 250;

                                            Guid work = item.Id;
                                            //工步路线规则
                                            foreach (var temp in workStepList)
                                            {
                                                ProcessLine processWorkLine = new ProcessLine();
                                                processWorkLine.PPtr = item.Id;
                                                processWorkLine.BopDescId = bopDesc.Id;
                                                processWorkLine.From = temp.Id;
                                                processWorkLine.To = work;
                                                work = temp.Id;
                                                _processLineRepository.Insert(processWorkLine);
                                                temp.Figure = "RoundedRectangle";
                                                temp.Color = "black";
                                                temp.Size = 0;
                                                temp.Fill = "lightgray";
                                                workX = workX + 300.00;
                                                temp.Loc = workX.ToString() + " " + workY.ToString();
                                                _workStepEntityRepository.Update(temp);
                                            }
                                        }

                                    }
                                }
                            }
                         
                            var lotNo = _bopDescRepository.Get(bop.BopDescId).LotNo;
                            var tech = _techniqueEntityRepository.Get(input.TechniqueEntityId);
                            var edition = lotNo + "-001";
                            tech.Edition = edition;
                            tech.FileStatus = FileStatus.已发布;
                            _techniqueEntityRepository.Update(tech);
                        }

                    }
                    else
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "只有3、4级节点才能绑定工艺规程文件!";
                        return resultMessage;
                        //throw new UserFriendlyException("只有3、4级节点才能绑定工艺规程文件!");
                    }
                }
                else
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "只有叶节点才能绑定工艺规程文件!";
                    return resultMessage;
                    //throw new UserFriendlyException("只有叶节点才能绑定工艺规程文件!");
                }
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }
        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <param name="miniDouble"></param>
        /// <param name="maxiDouble"></param>
        /// <returns></returns>
        protected static double NextDouble(double miniDouble, double maxiDouble)
        {
            Random random = new Random();
            double num = maxiDouble - miniDouble;
            if (num <= double.MaxValue)
            {
                var ran = random.NextDouble();
                var numRes = (ran * (double)num) + miniDouble;
                return numRes;
            }
            int RandNum = random.Next();
            if ((random.Next() % 2 == 0) ? true : false)
            {
                num = -num;
            }
            double num2 = num;
            num2 += 2147483646.0;
            num2 = num2 / 4294967293.0;
            return (num2 * (double)num) + miniDouble;

        }
    }
}
